#include <stdlib.h>
#include "includes.h"
#include "mtype.h"
#include "hmc830LP6GE_type.h"
#include "hmc830LP6GE.h"
#include "adf4001.h"

/*
*********************************************************************************************************
*                                                CONSTANTS
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                                VARIABLES
*********************************************************************************************************
*/
extern OS_EVENT *consol_q;
USR_INT08U	*gcmdptr;
//USR_INT32U	grd_reg03;
//USR_INT32U	grd_reg04;

USR_INT08U	gch_curr;
USR_INT08U	reg_addr;
USR_INT32U	reg_valu;
USR_FP32	freq;
USR_INT08U	reg_valu_str[8];
USR_INT08U	gain;

struct CMDLIST{
	USR_INT08U	*p_arg;
	struct CMDLIST *p_n;
}arg[5];
/*
*********************************************************************************************************
*                                            FUNCTION PROTOTYPES
*********************************************************************************************************
*/
static void ParseCmd(USR_INT08U *tPtr);
static USR_INT16S rul_check(const USR_INT08U *lptr, CHECKRULE lrule);
static void to_upper(USR_INT08U *lptr);
static USR_INT32U hstr2i(const USR_INT08U *lptr);
static void i2hstr(const USR_INT32U dat, USR_INT08U *ldst);

void AppHmc830Task(void *p_arg)
{
	USR_INT08U  err;
	(void)p_arg;
	
	init_channal(1);
	freq = 50000.0;
	out_freq(1, freq);
//	while(1){
//		OSTimeDlyHMSM(0, 0, 1, 0);
//	}
	while(1){
		freq -= 5000.0;
		if(freq < 25000.0){
			freq = 50000.0;
		}
		OSTimeDlyHMSM(0, 0, 2, 0);
		out_freq(1, freq);
	}
//	init_4001(1);
	arg[0].p_arg = USR_NULL;
	arg[1].p_arg = USR_NULL;
	arg[2].p_arg = USR_NULL;
	arg[3].p_arg = USR_NULL;
	arg[4].p_arg = USR_NULL;
	while(USR_TRUE){
		gcmdptr = OSQPend(consol_q, 0, &err);
		if(gcmdptr != USR_NULL){
			ParseCmd(gcmdptr);
		}
	}
}
/*********************************************************************
 * Name        : static void ParseCmd(void)
 * Function    : execute the cmd
 * PreCondition: None
 * Input       : None
 * Output      : None
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
static void ParseCmd(USR_INT08U *tPtr)
{
	USR_INT16S i = 0;
	USR_INT08U space = 1;
	if(-1 == rul_check(tPtr, ILLIGLE_CH)){
		goto parserend;
	}
	arg[0].p_arg = USR_NULL;
	arg[1].p_arg = USR_NULL;
	arg[2].p_arg = USR_NULL;
	arg[3].p_arg = USR_NULL;
	arg[4].p_arg = USR_NULL;
	while(*tPtr != '\0' && i < sizeof(arg) / sizeof(struct CMDLIST) + 1){		// splite the cmd string to list
		if(*tPtr == ' '){
			if(space == 0){
				space = 1;
				*tPtr = '\0';
			}
		}
		else{
			if(space == 1){
				space = 0;
				arg[i].p_arg = tPtr;
				i ++;
			}
		}
		tPtr ++;
	}
	to_upper(&arg[0].p_arg[0]);
	to_upper(&arg[1].p_arg[0]);
	to_upper(&arg[2].p_arg[0]);
	to_upper(&arg[3].p_arg[0]);
	to_upper(&arg[4].p_arg[0]);
	
	if(-1 == rul_check(&arg[0].p_arg[0], WORD_CH)){
		goto parserend;
	}
	if(arg[0].p_arg[0] == 'R' && arg[0].p_arg[1] == 'D'){			// read register value from hmc830
		if(-1 == rul_check(&arg[1].p_arg[0], WORD_CH)){				// char check
			goto parserend;
		}
		if(-1 == rul_check(&arg[2].p_arg[0], HEXNUMB_CH)){			// channal number check
			goto parserend;
		}
		if(-1 == rul_check(&arg[3].p_arg[0], HEXNUMB_CH)){			// register address check
			goto parserend;
		}
		if(arg[1].p_arg[0] == 'P' && arg[1].p_arg[1] == 'L' && arg[1].p_arg[2] == 'L'){
			gch_curr = hstr2i(&arg[2].p_arg[0]);
			reg_addr = hstr2i(&arg[3].p_arg[0]);
			reg_valu = read_pll(gch_curr, reg_addr);
			// display the reg value;
			if(reg_valu != -1){
				echo_str("\r\n", 2);
				echo_str("read ok!", 8);
			}
		}
	}
	else if(arg[0].p_arg[0] == 'P' && arg[0].p_arg[1] == 'R'){		// read operation
		if(-1 == rul_check(&arg[1].p_arg[0], WORD_CH)){				// char check
			goto parserend;
		}
		if(-1 == rul_check(&arg[2].p_arg[0], HEXNUMB_CH)){			// channal number check
			goto parserend;
		}
		if(-1 == rul_check(&arg[3].p_arg[0], HEXNUMB_CH)){			// register address check
			goto parserend;
		}
		if(arg[1].p_arg[0] == 'P' && arg[1].p_arg[1] == 'L' && arg[1].p_arg[2] == 'L'){
			gch_curr = hstr2i(&arg[2].p_arg[0]);
			reg_addr = hstr2i(&arg[3].p_arg[0]);
			reg_valu = print_pll(gch_curr, reg_addr);
			// display the reg value;
			if(reg_valu != -1){
				i2hstr(reg_valu, reg_valu_str);
				echo_str("\r\n", 2);
				echo_str("PLL VAL=:", sizeof("PLL VAL=:"));
				echo_str((const USR_CHAR *)reg_valu_str, 8);
			}
		}
		if(arg[1].p_arg[0] == 'V' && arg[1].p_arg[1] == 'C' && arg[1].p_arg[2] == 'O'){
			gch_curr = hstr2i(&arg[2].p_arg[0]);
			reg_addr = hstr2i(&arg[3].p_arg[0]);
			reg_valu = print_vco(gch_curr, reg_addr);
			// display the reg value;
			if(reg_valu != -1){
				i2hstr(reg_valu, reg_valu_str);
				echo_str("\r\n", 2);
				echo_str("VCO VAL=:", sizeof("VCO VAL=:"));
				echo_str((const USR_CHAR *)reg_valu_str, 8);
			}
		}
	}
	else if(arg[0].p_arg[0] == 'W' && arg[0].p_arg[1] == 'R'){		// write operation
		if(-1 == rul_check(&arg[1].p_arg[0], WORD_CH)){				// char check
			goto parserend;
		}
		if(-1 == rul_check(&arg[2].p_arg[0], HEXNUMB_CH)){			// channal number check
			goto parserend;
		}
		if(-1 == rul_check(&arg[3].p_arg[0], HEXNUMB_CH)){			// register address check
			goto parserend;
		}
		if(-1 == rul_check(&arg[4].p_arg[0], HEXNUMB_CH)){			// register value check
			goto parserend;
		}
			gch_curr = hstr2i(&arg[2].p_arg[0]);
			reg_addr = hstr2i(&arg[3].p_arg[0]);
			reg_valu = hstr2i(&arg[4].p_arg[0]);
		if(arg[1].p_arg[0] == 'P' && arg[1].p_arg[1] == 'L' && arg[1].p_arg[2] == 'L'){
			write_pll(gch_curr, reg_addr, reg_valu);
		}
		else if(arg[1].p_arg[0] == 'V' && arg[1].p_arg[1] == 'C' && arg[1].p_arg[2] == 'O'){
			write_vco(gch_curr, reg_addr, reg_valu);
		}
	}
	else if(arg[0].p_arg[0] == 'F' && arg[0].p_arg[1] == 'Q'){		// change output frequence
		if(-1 == rul_check(&arg[1].p_arg[0], HEXNUMB_CH)){			// channal number check
			goto parserend;
		}
		if(-1 == rul_check(&arg[2].p_arg[0], OCTNUMB_CH)){			// float check
			goto parserend;
		}
		gch_curr = hstr2i(&arg[1].p_arg[0]);
		freq = atof((const USR_CHAR *)&arg[2].p_arg[0]);
		out_freq(gch_curr, freq);
// test		
		reg_valu = print_pll(gch_curr, REG03H);
		i2hstr(reg_valu, reg_valu_str);
		echo_str("\r\n", 2);
		echo_str("REG03H:", 7);
		echo_str((const USR_CHAR *)reg_valu_str, 8);
			
		reg_valu = print_pll(gch_curr, REG04H);
		i2hstr(reg_valu, reg_valu_str);
		echo_str("\r\n", 2);
		echo_str("REG04H:", 7);
		echo_str((const USR_CHAR *)reg_valu_str, 8);
		
		reg_valu = print_vco(gch_curr, VCO_REG02H);
		i2hstr(reg_valu, reg_valu_str);
		echo_str("\r\n", 2);
		echo_str("VCO_REG02H:", 11);
		echo_str((const USR_CHAR *)reg_valu_str, 8);
// test end
	}
	else if(arg[0].p_arg[0] == 'G' && arg[0].p_arg[1] == 'A'){		// change gain
		if(-1 == rul_check(&arg[1].p_arg[0], HEXNUMB_CH)){			// channal number check
			goto parserend;
		}
		if(-1 == rul_check(&arg[2].p_arg[0], OCTNUMB_CH)){			// gain check
			goto parserend;
		}
		gch_curr = hstr2i(&arg[1].p_arg[0]);
		gain = atoi(&arg[2].p_arg[0]);
		chage_gain(gch_curr, gain);
	}
// adf4001 test
	else if(arg[0].p_arg[0] == 'A' && arg[0].p_arg[1] == 'D' && arg[0].p_arg[2] == 'F'){
		if(-1 == rul_check(&arg[1].p_arg[0], HEXNUMB_CH)){			// channal number check
			goto parserend;
		}
		if(-1 == rul_check(&arg[3].p_arg[0], HEXNUMB_CH)){			// gain check
			goto parserend;
		}
		gch_curr = hstr2i(&arg[1].p_arg[0]);
		reg_valu = hstr2i(&arg[3].p_arg[0]);
		if(arg[2].p_arg[0] == 'R'){
			write_r_cter(gch_curr, reg_valu);
		}
		else if(arg[2].p_arg[0] == 'N'){
			write_n_cter(gch_curr, reg_valu);
		}
		else if(arg[2].p_arg[0] == 'F'){
			write_func(gch_curr, reg_valu);
		}
		else if(arg[2].p_arg[0] == 'I'){
			write_init(gch_curr, reg_valu);
		}
	}
// adf4001 test end
	else{
		echo_str("\r\nIllegal Commend!", sizeof("\r\nIllegal Commend!"));
	}
parserend:
	echo_str("\r\n>>> ", 6);
}

/*********************************************************************
 * Name        : static USR_INT16S rul_check(const USR_INT08U *lptr, CHECKRULE lrule)
 * Function    : check the cmd argumment if have illegal character or not
 * PreCondition: None
 * Input       : None
 * Output      : None
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
static USR_INT16S rul_check(const USR_INT08U *lptr, CHECKRULE lrule)
{
	if(lptr == USR_NULL){
		return -1;
	}
		switch(lrule){
		case ILLIGLE_CH:
			while(*lptr != '\0'){
				if(!(*lptr == ' ' || (*lptr >= '0' && *lptr <= '9') || *lptr == '.' || (*lptr >= 'A' && *lptr <= 'Z') || (*lptr >= 'a' && *lptr <= 'z'))){
					echo_str("\r\nIllegal character:'", sizeof("\r\nillegal character:'"));
					echo_char(*lptr);
					echo_str("'.", 2);
					return -1;
				}
				lptr ++;
			}
			break;
		case OCTNUMB_CH:
			while(*lptr != '\0'){
				if(!(*lptr == '.' || (*lptr >= '0' && *lptr <= '9'))){
					echo_str("\r\nIllegal character:'", sizeof("\r\nillegal character:'"));
					echo_char(*lptr);
					echo_str("'.", 2);
					return -1;
				}
				lptr ++;
			}
			break;
		case HEXNUMB_CH:
			while(*lptr != '\0'){
				if(!((*lptr >= '0' && *lptr <= '9') || (*lptr >= 'A' && *lptr <= 'F') || (*lptr >= 'a' && *lptr <= 'z'))){
					echo_str("\r\nIllegal character:'", sizeof("\r\nillegal character:'"));
					echo_char(*lptr);
					echo_str("'.", 2);
					return -1;
				}
				lptr ++;
			}
			break;
		case WORD_CH:
			while(*lptr != '\0'){
				if(!((*lptr >= 'A' && *lptr <= 'Z') || (*lptr >= 'a' && *lptr <= 'z'))){
					echo_str("\r\nIllegal character:'", sizeof("\r\nillegal character:'"));
					echo_char(*lptr);
					echo_str("'.", 2);
					return -1;
				}
				lptr ++;
			}
			break;
		default :
			return -1;
			break;
		}
	return 0;
}

/*********************************************************************
 * Name        : static void to_upper(USR_INT08U *lptr)
 * Function    : change the little character to big
 * PreCondition: None
 * Input       : None
 * Output      : None
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
static void to_upper(USR_INT08U *lptr)
{
	if(lptr != USR_NULL){
		while(*lptr != '\0'){
			if(*lptr >= 'a' && *lptr <= 'z'){
				*lptr -= 'a' - 'A';
			}
			*lptr ++;
		}
	}
}

/*********************************************************************
 * Name        : static USR_INT32U hstr2i(const USR_INT08U *lptr)
 * Function    : chage the hex ascii string to 32bits long
 * PreCondition: None
 * Input       : None
 * Output      : None
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
static USR_INT32U hstr2i(const USR_INT08U *lptr)
{
	USR_INT32U result = 0;
	const char hex[]="0123456789ABCDEF";
	const char hexl[]="0123456789abcdef";
	int i;
	while(*lptr != '\0'){
		for(i=0; i < 16;i++){
			if(*lptr == hex[i] || *lptr == hexl[i]) break;
		}
		if(i==16) return 0;
		result <<= 4;
		result += i;
		lptr ++;
	}
	return result;
}

/*********************************************************************
 * Name        : static void i2hstr(const USR_INT32U dat, USR_INT08U *ldst)
 * Function    : chage the 32bits long to hex ascii string
 * PreCondition: None
 * Input       : None
 * Output      : None
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
static void i2hstr(const USR_INT32U dat, USR_INT08U *ldst)
{
//	USR_INT32U result = 0;
	const char hex[]="0123456789ABCDEF";
	int i;
	USR_INT08U *tptr = (USR_INT08U *)&dat;
	
	if(ldst == USR_NULL){return;}
	tptr += 3;
	
	for(i=0; i < 4;i++){
		*ldst++ = hex[*tptr >> 4];
		*ldst++ = hex[*tptr & 0x0F];
		tptr --;
	}
}
